#pragma once
#include "Runtime/BattleFirePrefix.h"

namespace Alice
{
    class FTaskBase;
    class FPrerequisites
    {
    public:
        void Push(FTaskBase*inPrerequisite)
        {
            mMutex.lock();
            mPrerequisites.push_back(inPrerequisite);
            mMutex.unlock();
        }
		std::vector<FTaskBase*> mPrerequisites;
        std::mutex mMutex;
    };
    class FTaskBase
    {
    public:
        FPrerequisites mPrerequisites;
        // The task will be executed only when all prerequisites are completed. The task type must be a task handle that holds a pointer to
        // FTaskBase as its `Pimpl` member (see Tasks::TTaskBase).
        // Must not be called concurrently
        bool AddPrerequisites(FTaskBase* inPrerequisite)
        {
            mPrerequisites.Push(inPrerequisite);
            return true;
        }
    };
    // an extension of FTaskBase for tasks that return a result.
    // Stores task execution result and provides an access to it.
    template<typename ResultType>
    class TTaskWithResult : public FTaskBase
    {
    public:
    };
    // a specialization for tasks that don't return results
    /*template<typename TaskBodyType>
    class TExecutableTaskBase<TaskBodyType> : public FTaskBase
    {
    public:
    };*/
    // a special kind of task that is used for signalling or dependency management. It can have prerequisites or be used as a prerequisite for other tasks. 
    // It's optimized for the fact that it doesn't have a task body and so doesn't need to be scheduled and executed
    class FTaskEventBase : public FTaskBase
    {
    public:
    };
    // a common part of the generic `TTask<ResultType>` and its `TTask<void>` specialisation
    class FTaskHandle
    {
    public:
        FTaskBase*mTaskBase;
        // waits for task's completion without timeout. Tries to retract the task and execute it in-place, if failed - blocks until the task 
        // is completed by another thread.
        // @return true if the task is completed
        bool Wait() const
        {
            // we keep the return type as boolean even if always returning true
            // as we could merge some versions of the Wait API back at some point.
            return true;
        }
    };
    using FTask=FTaskHandle;
    class FEventTask:public FTaskHandle
    {
    public:
        // all prerequisites must be added before triggering the event
        template<typename PrerequisitesType>
        void AddPrerequisites(const PrerequisitesType& Prerequisites)
        {
            mTaskBase->AddPrerequisites(Prerequisites);
        }
    };
}